
#ifndef PARSER_H
#define PARSER_H

#include <bitset>
#include "Scanner.h"
#include "SymbolTable.h"
#include "Item.h"

namespace mjc {

	class Code;

	class Parser
	{
	public:
		static enum Op
		{
			OP_EQ,
			OP_NE,
			OP_LT,
			OP_LE,
			OP_GT,
			OP_GE,
			OP_UNKNOWN
		};

	private:
		Scanner scanner;
		SymbolTable symbolTable;
		Code* code;

		std::bitset<64> exprStart,  
						statStart,  
						statSeqFollow,  
						declStart,  
						declFollow;

		Token currentToken;
		Token lookaheadToken;
		Object* currentMethod;//points to the current method being parsed

		int errorCount;
		int errorDistance;// n of correctly recognized tokens since last error

		void Scan();//reads next token
		
		void Check(const TokenType::Type& expected);
		

		void Program();
		void ConstDecl();
		void VarDecl();
		void MethodDecl();
		void ClassDecl();
		Type Type();
		void FormPars();
		void Block();
		void Statement();
		void ActPars(Item& item);
		Op Condition();
		Item Expr();
		Item Designator();
		Op Relop();
		Item Term();
		Item Factor();

		void AddObject(Object& object);//adds an object to the current scope
		void InitBitsets();

	public:
		Parser(std::wstreambuf* inbuf);
		Parser(Scanner& scanner);
		~Parser();
		
		void Parse();
		Code* GetCode() const { return code; }
		int GetErrorCount(){ return errorCount; }
		void Error(const std::wstring& msg);
		void PrintSymbolTable();
	};
}

#endif